package com.xci.core.aspect;

import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.xci.core.annotation.Paged;
import com.xci.core.annotation.Top;
import com.xci.core.base.SMap;
import com.xci.core.domain.PageModel;
import com.xci.core.exceptions.AppException;
import com.xci.core.helper.Helper;
import com.xci.core.helper.ObjectHelper;
import com.xci.core.helper.WebHelper;
import com.xci.core.internal.Const;
import com.xci.core.internal.Sys;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 数据库分页拦截器
 *
 * @author 吕艳阳
 */
@Aspect
@Slf4j
@Component
public class DbPageAspect {

    @Before("@annotation(com.xci.core.annotation.Top)")
    public void doTopDataList(JoinPoint joinPoint) {
        var method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        var fd = method.getAnnotation(Top.class);

        PageModel pageModel = new PageModel();
        pageModel.setPageIndex(1);
        pageModel.setPageSize(fd.count());
        pageModel.setSortName(WebHelper.getParameter(fd.sortNameField(), fd.defaultSortName()));
        pageModel.setSortDir(WebHelper.getParameter(fd.sortDirField(), fd.defaultSortDir()));

        String orderBy = Const.EMPTY;
        if (fd.allowSort() && !pageModel.getSortName().isEmpty()) {
            SMap sortNameMap = getSortNameMap(fd.sortNameMap());
            orderBy = getMapSingleFieldSort(pageModel, fd.sortNameConvertType(),sortNameMap);
        }

        int maxPageSize = Sys.setting().getApp().getSysApiMaxPageSize();
        int page = pageModel.getPageIndex();
        int limit = pageModel.getPageSize();

        if (limit > maxPageSize) {
            throw new AppException(Helper.format("每页最大不能超过{}条记录,当前:{}", maxPageSize, limit));
        }

        if (!orderBy.isEmpty()) {
            PageHelper.startPage(page, limit, orderBy);
        } else {
            PageHelper.startPage(page, limit);
        }
    }

    @Before("@annotation(com.xci.core.annotation.Paged)")
    public void doPageDataList(JoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Paged pd = method.getAnnotation(Paged.class);
        PageModel pageModel = new PageModel();
        pageModel.setPageIndex(WebHelper.getParameterToInt(pd.pageIndexField(), pd.defaultPageIndex()));
        pageModel.setPageSize(WebHelper.getParameterToInt(pd.pageSizeField(), pd.defaultPageSize()));
        pageModel.setSortName(WebHelper.getParameter(pd.sortNameField(), pd.defaultSortName()));
        pageModel.setSortDir(WebHelper.getParameter(pd.sortDirField(), pd.defaultSortDir()));

        String orderBy = Const.EMPTY;
        if (pd.allowSort() && !pageModel.getSortName().isEmpty()) {
            SMap sortNameMap = getSortNameMap(pd.sortNameMap());
            if (pd.allowMultiSort()) {
                orderBy = getMapMultiFieldSort(pageModel, pd.sortNameConvertType(),sortNameMap);
            } else {
                orderBy = getMapSingleFieldSort(pageModel, pd.sortNameConvertType(),sortNameMap);
            }
        }

        int maxPageSize = Sys.setting().getApp().getSysApiMaxPageSize();
        int page = pageModel.getPageIndex();
        int limit = pageModel.getPageSize();

        if (page <= 0 || limit <= 0) {
            throw new RuntimeException("错误的分页参数,分页参数必须都是正整数并大于0.");
        }
        if (limit > maxPageSize) {
            throw new AppException(Helper.format("每页最大不能超过{}条记录,当前:{}", maxPageSize, limit));
        }

        if (!orderBy.isEmpty()) {
            PageHelper.startPage(page, limit, orderBy);
        } else {
            PageHelper.startPage(page, limit);
        }
    }

    // private PageModel convertToPageModel(Map<String, Object> params, DbPage pd) {
    //     String pageIndexField = pd.pageIndexField();
    //     String pageSizeField = pd.pageSizeField();
    //     String sortNameField = pd.sortNameField();
    //     String sortDirField = pd.sortDirField();
    //     PageModel model = new PageModel();
    //     model.setPageIndex(Convert.toInt(params.get(pageIndexField), null));
    //     model.setPageSize(Convert.toInt(params.get(pageSizeField), null));
    //     if (params.containsKey(sortNameField)) {
    //         model.setSortName(params.get(sortNameField).toString());
    //     }
    //     if (params.containsKey(sortDirField)) {
    //         model.setSortDir(params.get(sortDirField).toString());
    //     }
    //     return model;
    // }

    private SMap getSortNameMap(String[] sortNameMapArray){
        SMap map = SMap.newMap();
        for (String item : sortNameMapArray) {
            var names = Helper.splitToArray(item,':');
            if (names.length!=2){
                continue;
            }
            map.put(names[0],names[1]);
        }
        return map;
    }

    private String getMapSingleFieldSort(PageModel pageModel, int sortNameConvertType, SMap sortNameMap) {
        if (pageModel.getSortName().isEmpty()) {
            return Const.EMPTY;
        }
        if (pageModel.getSortDir().isEmpty()) {
            pageModel.setSortDir("asc");
        }
        String orderBy = Helper.format("{} {}", getSortName(pageModel.getSortName(), sortNameConvertType,sortNameMap),
                pageModel.getSortDir());
        return Helper.escapeOrderBySql(orderBy);
    }

    private String getMapMultiFieldSort(PageModel pageModel, int sortNameConvertType, SMap sortNameMap) {
        String[] sorts = Helper.splitToArray(pageModel.getSortName());
        String[] orders = Helper.splitToArray(pageModel.getSortDir());

        if (ObjectHelper.isEmpty(sorts)) {
            return Const.EMPTY;
        }
        if (ObjectHelper.isEmpty(orders)) {
            orders = new String[sorts.length];
            for (int i = 0; i < sorts.length; i++) {
                orders[i] = "asc";
            }
        }
        StringBuilder orderby = new StringBuilder();
        for (int i = 0; i < sorts.length; i++) {
            String sname = sorts[i];
            String sorder = orders[i];
            orderby.append(Helper.format("{} {}", getSortName(sname, sortNameConvertType,sortNameMap), sorder));
            if (i != sorts.length - 1) {
                orderby.append(",");
            }
        }

        return Helper.escapeOrderBySql(orderby.toString());
    }

    private String getSortName(String name, int sortNameConvertType, SMap sortNameMap) {
        String resultName = name;
        String mapName = sortNameMap.get(name);
        if (Helper.isNotEmpty(mapName)) {
            resultName = mapName;
        }
        if (sortNameConvertType == 1) { //1驼峰转下划线
            return StrUtil.toUnderlineCase(resultName);
        } else if (sortNameConvertType == 2) { //2下划线转驼峰
            return StrUtil.toCamelCase(resultName);
        }
        return resultName;
    }
}